

 /*
 This file '_widget' is part of Firebird Integrated Solution 1.0

 Copyright (c) 2015 Lincong

 Contact:  
        Email: lincong1987@gmail.com

        QQ: 159257119
 
 See Usage at http://www.jplatformx.com/firebird

 Create date: 2015-07-14 04:21
 */

 (function ($, undefined) {

     var uuid = 0,
         slice = Array.prototype.slice,
         _cleanData = $.cleanData;
     $.cleanData = function (elems) {
         for (var i = 0, elem; (elem = elems[i]) != null; i++) {
             try {
                 $(elem).triggerHandler("remove");
                 // http://bugs.jquery.com/ticket/8235
             } catch (e) {
             }
         }
         _cleanData(elems);
     };

     $.widget = function (name, base, prototype) {
         var fullName, existingConstructor, constructor, basePrototype,
             namespace = name.split(".")[0];

         name = name.split(".")[1];
         fullName = namespace + "-" + name;

         if (!prototype) {
             prototype = base;
             base = $.Widget;
         }

         // create selector for plugin
         $.expr[":"][fullName.toLowerCase()] = function (elem) {
             return !!$.data(elem, fullName);
         };

         $[namespace] = $[namespace] || {};
         existingConstructor = $[namespace][name];
         constructor = $[namespace][name] = function (options, element) {
             // allow instantiation without "new" keyword
             if (!this._createWidget) {
                 return new constructor(options, element);
             }

             // allow instantiation without initializing for simple inheritance
             // must use "new" keyword (the code above always passes args)
             if (arguments.length) {
                 this._createWidget(options, element);
             }
         };
         // extend with the existing constructor to carry over any static properties
         $.extend(constructor, existingConstructor, {
             version: prototype.version,
             // copy the object used to create the prototype in case we need to
             // redefine the widget later
             _proto: $.extend({}, prototype),
             // track widgets that inherit from this widget in case this widget is
             // redefined after a widget inherits from it
             _childConstructors: []
         });

         basePrototype = new base();
         // we need to make the options hash a property directly on the new instance
         // otherwise we'll modify the options hash on the prototype that we're
         // inheriting from
         basePrototype.options = $.widget.extend({}, basePrototype.options);
         $.each(prototype, function (prop, value) {
             if ($.isFunction(value)) {
                 prototype[prop] = (function () {
                     var _super = function () {
                             return base.prototype[prop].apply(this, arguments);
                         },
                         _superApply = function (args) {
                             return base.prototype[prop].apply(this, args);
                         };
                     return function () {
                         var __super = this._super,
                             __superApply = this._superApply,
                             returnValue;

                         this._super = _super;
                         this._superApply = _superApply;

                         returnValue = value.apply(this, arguments);

                         this._super = __super;
                         this._superApply = __superApply;

                         return returnValue;
                     };
                 })();
             }
         });
         constructor.prototype = $.widget.extend(basePrototype, {
             // TODO: remove support for widgetEventPrefix
             // always use the name + a colon as the prefix, e.g., draggable:start
             // don't prefix for widgets that aren't DOM-based
             widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
         }, prototype, {
             constructor: constructor,
             namespace: namespace,
             widgetName: name,
             // TODO remove widgetBaseClass, see #8155
             widgetBaseClass: fullName,
             widgetFullName: fullName
         });

         // If this widget is being redefined then we need to find all widgets that
         // are inheriting from it and redefine all of them so that they inherit from
         // the new version of this widget. We're essentially trying to replace one
         // level in the prototype chain.
         if (existingConstructor) {
             $.each(existingConstructor._childConstructors, function (i, child) {
                 var childPrototype = child.prototype;

                 // redefine the child widget using the same prototype that was
                 // originally used, but inherit from the new version of the base
                 $.widget(childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto);
             });
             // remove the list of existing child constructors from the old constructor
             // so the old child constructors can be garbage collected
             delete existingConstructor._childConstructors;
         } else {
             base._childConstructors.push(constructor);
         }

         $.widget.bridge(name, constructor);
     };

     $.widget.extend = function (target) {
         var input = slice.call(arguments, 1),
             inputIndex = 0,
             inputLength = input.length,
             key,
             value;
         for (; inputIndex < inputLength; inputIndex++) {
             for (key in input[inputIndex]) {
                 value = input[inputIndex][key];
                 if (input[inputIndex].hasOwnProperty(key) && value !== undefined) {
                     // Clone objects
                     if ($.isPlainObject(value)) {
                         target[key] = $.isPlainObject(target[key]) ?
                             $.widget.extend({}, target[key], value) :
                             // Don't extend strings, arrays, etc. with objects
                             $.widget.extend({}, value);
                         // Copy everything else by reference
                     } else {
                         target[key] = value;
                     }
                 }
             }
         }
         return target;
     };

     $.widget.bridge = function (name, object) {
         var fullName = object.prototype.widgetFullName || name;
         $.fn[name] = function (options) {
             var isMethodCall = typeof options === "string",
                 args = slice.call(arguments, 1),
                 returnValue = this;

             // allow multiple hashes to be passed on init
             options = !isMethodCall && args.length ?
                 $.widget.extend.apply(null, [options].concat(args)) :
                 options;

             if (isMethodCall) {
                 this.each(function () {
                     var methodValue,
                         instance = $.data(this, fullName);
                     if (!instance) {
                         return $.error("cannot call methods on " + name + " prior to initialization; " +
                             "attempted to call method '" + options + "'");
                     }
                     if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
                         return $.error("no such method '" + options + "' for " + name + " widget instance");
                     }
                     methodValue = instance[options].apply(instance, args);
                     if (methodValue !== instance && methodValue !== undefined) {
                         returnValue = methodValue && methodValue.jquery ?
                             returnValue.pushStack(methodValue.get()) :
                             methodValue;
                         return false;
                     }
                 });
             } else {
                 this.each(function () {
                     var instance = $.data(this, fullName);
                     if (instance) {
                         instance.option(options || {})._init();
                     } else {
                         $.data(this, fullName, new object(options, this));
                     }
                 });
             }

             return returnValue;
         };
     };

     $.Widget = function (/* options, element */) {
     };
     $.Widget._childConstructors = [];

     $.Widget.prototype = {
         widgetName: "widget",
         widgetEventPrefix: "",
         defaultElement: "<div>",
         options: {
             disabled: false,

             // callbacks
             create: null
         },
         _createWidget: function (options, element) {
             element = $(element || this.defaultElement || this)[0];
             this.element = $(element);
             this.uuid = uuid++;
             this.eventNamespace = "." + this.widgetName + this.uuid;
             this.options = $.widget.extend({},
                 this.options,
                 this._getCreateOptions(),
                 options);

             this.bindings = $();
             this.hoverable = $();
             this.focusable = $();

             if (element !== this) {
                 // 1.9 BC for #7810
                 // TODO remove dual storage
                 $.data(element, this.widgetName, this);
                 $.data(element, this.widgetFullName, this);
                 this._on(true, this.element, {
                     remove: function (event) {
                         if (event.target === element) {
                             this.destroy();
                         }
                     }
                 });
                 this.document = $(element.style ?
                     // element within the document
                     element.ownerDocument :
                     // element is window or document
                 element.document || element);
                 this.window = $(this.document[0].defaultView || this.document[0].parentWindow);
             }

             this._create();
             this._trigger("create", null, this._getCreateEventData());
             this._init();
         },
         _getCreateOptions: $.noop,
         _getCreateEventData: $.noop,
         _create: $.noop,
         _init: $.noop,

         destroy: function () {
             this._destroy();
             // we can probably remove the unbind calls in 2.0
             // all event bindings should go through this._on()
             this.element
                 .unbind(this.eventNamespace)
                 // 1.9 BC for #7810
                 // TODO remove dual storage
                 .removeData(this.widgetName)
                 .removeData(this.widgetFullName)
                 // support: jquery <1.6.3
                 // http://bugs.jquery.com/ticket/9413
                 .removeData($.camelCase(this.widgetFullName));
             this.widget()
                 .unbind(this.eventNamespace)
                 .removeAttr("aria-disabled")
                 .removeClass(
                 this.widgetFullName + "-disabled " +
                 "ui-state-disabled");

             // clean up events and states
             this.bindings.unbind(this.eventNamespace);
             this.hoverable.removeClass("ui-state-hover");
             this.focusable.removeClass("ui-state-focus");
         },
         _destroy: $.noop,

         widget: function () {
             return this.element;
         },

         option: function (key, value) {
             var options = key,
                 parts,
                 curOption,
                 i;

             if (arguments.length === 0) {
                 // don't return a reference to the internal hash
                 return $.widget.extend({}, this.options);
             }

             if (typeof key === "string") {
                 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
                 options = {};
                 parts = key.split(".");
                 key = parts.shift();
                 if (parts.length) {
                     curOption = options[key] = $.widget.extend({}, this.options[key]);
                     for (i = 0; i < parts.length - 1; i++) {
                         curOption[parts[i]] = curOption[parts[i]] || {};
                         curOption = curOption[parts[i]];
                     }
                     key = parts.pop();
                     if (value === undefined) {
                         return curOption[key] === undefined ? null : curOption[key];
                     }
                     curOption[key] = value;
                 } else {
                     if (value === undefined) {
                         return this.options[key] === undefined ? null : this.options[key];
                     }
                     options[key] = value;
                 }
             }

             this._setOptions(options);

             return this;
         },
         _setOptions: function (options) {
             var key;

             for (key in options) {
                 this._setOption(key, options[key]);
             }

             return this;
         },
         _setOption: function (key, value) {
             this.options[key] = value;

             if (key === "disabled") {
                 this.widget()
                     .toggleClass(this.widgetFullName + "-disabled ui-state-disabled", !!value)
                     .attr("aria-disabled", value);
                 this.hoverable.removeClass("ui-state-hover");
                 this.focusable.removeClass("ui-state-focus");
             }

             return this;
         },

         enable: function () {
             return this._setOption("disabled", false);
         },
         disable: function () {
             return this._setOption("disabled", true);
         },

         _on: function (suppressDisabledCheck, element, handlers) {
             var delegateElement,
                 instance = this;

             // no suppressDisabledCheck flag, shuffle arguments
             if (typeof suppressDisabledCheck !== "boolean") {
                 handlers = element;
                 element = suppressDisabledCheck;
                 suppressDisabledCheck = false;
             }

             // no element argument, shuffle and use this.element
             if (!handlers) {
                 handlers = element;
                 element = this.element;
                 delegateElement = this.widget();
             } else {
                 // accept selectors, DOM elements
                 element = delegateElement = $(element);
                 this.bindings = this.bindings.add(element);
             }

             $.each(handlers, function (event, handler) {
                 function handlerProxy() {
                     // allow widgets to customize the disabled handling
                     // - disabled as an array instead of boolean
                     // - disabled class as method for disabling individual parts
                     if (!suppressDisabledCheck &&
                         ( instance.options.disabled === true ||
                         $(this).hasClass("ui-state-disabled") )) {
                         return;
                     }
                     return ( typeof handler === "string" ? instance[handler] : handler )
                         .apply(instance, arguments);
                 }

                 // copy the guid so direct unbinding works
                 if (typeof handler !== "string") {
                     handlerProxy.guid = handler.guid =
                         handler.guid || handlerProxy.guid || $.guid++;
                 }

                 var match = event.match(/^(\w+)\s*(.*)$/),
                     eventName = match[1] + instance.eventNamespace,
                     selector = match[2];
                 if (selector) {
                     delegateElement.delegate(selector, eventName, handlerProxy);
                 } else {
                     element.bind(eventName, handlerProxy);
                 }
             });
         },

         _off: function (element, eventName) {
             eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace;
             element.unbind(eventName).undelegate(eventName);
         },

         _delay: function (handler, delay) {
             function handlerProxy() {
                 return ( typeof handler === "string" ? instance[handler] : handler )
                     .apply(instance, arguments);
             }

             var instance = this;
             return setTimeout(handlerProxy, delay || 0);
         },

         _hoverable: function (element) {
             this.hoverable = this.hoverable.add(element);
             this._on(element, {
                 mouseenter: function (event) {
                     $(event.currentTarget).addClass("ui-state-hover");
                 },
                 mouseleave: function (event) {
                     $(event.currentTarget).removeClass("ui-state-hover");
                 }
             });
         },

         _focusable: function (element) {
             this.focusable = this.focusable.add(element);
             this._on(element, {
                 focusin: function (event) {
                     $(event.currentTarget).addClass("ui-state-focus");
                 },
                 focusout: function (event) {
                     $(event.currentTarget).removeClass("ui-state-focus");
                 }
             });
         },

         _trigger: function (type, event, data) {
             var prop, orig,
                 callback = this.options[type];

             data = data || {};
             event = $.Event(event);
             event.type = ( type === this.widgetEventPrefix ?
                 type :
             this.widgetEventPrefix + type ).toLowerCase();
             // the original event may come from any element
             // so we need to reset the target on the new event
             event.target = this.element[0];

             // copy original event properties over to the new event
             orig = event.originalEvent;
             if (orig) {
                 for (prop in orig) {
                     if (!( prop in event )) {
                         event[prop] = orig[prop];
                     }
                 }
             }

             this.element.trigger(event, data);
             return !( $.isFunction(callback) &&
             callback.apply(this.element[0], [event].concat(data)) === false ||
             event.isDefaultPrevented() );
         }
     };

     $.each({show: "fadeIn", hide: "fadeOut"}, function (method, defaultEffect) {
         $.Widget.prototype["_" + method] = function (element, options, callback) {
             if (typeof options === "string") {
                 options = {effect: options};
             }
             var hasOptions,
                 effectName = !options ?
                     method :
                     options === true || typeof options === "number" ?
                         defaultEffect :
                     options.effect || defaultEffect;
             options = options || {};
             if (typeof options === "number") {
                 options = {duration: options};
             }
             hasOptions = !$.isEmptyObject(options);
             options.complete = callback;
             if (options.delay) {
                 element.delay(options.delay);
             }
             if (hasOptions && $.effects && ( $.effects.effect[effectName] || $.uiBackCompat !== false && $.effects[effectName] )) {
                 element[method](options);
             } else if (effectName !== method && element[effectName]) {
                 element[effectName](options.duration, options.easing, callback);
             } else {
                 element.queue(function (next) {
                     $(this)[method]();
                     if (callback) {
                         callback.call(element[0]);
                     }
                     next();
                 });
             }
         };
     });

// DEPRECATED
     if ($.uiBackCompat !== false) {
         $.Widget.prototype._getCreateOptions = function () {
             return $.metadata && $.metadata.get(this.element[0])[this.widgetName];
         };
     }

 })(jQuery);